package grisar.gris;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import android.graphics.Point;

public class Map_Path {
	/**** Some constants *******************************************/
	private static final List<Character> connections = new ArrayList<Character>(
		    Arrays.asList('-', '+'));
	private static final List<Character> wayNodes = new ArrayList<Character>(
		    Arrays.asList('u', 'n', 'v', 'h'));
	// TODO fix these
	private static final Map<Character, Integer> yMods = new HashMap<Character, Integer>(){
		{put('u', -1); put('n', 1); put('U', -1); put('N', 1);}};
	private static final Map<Character, Integer> xMods = new HashMap<Character, Integer>(){
		{put('v', -1); put('h', 1); put('V', -1); put('H', 1);}};
	/*
	 * 0 = bakgrund
	 * - = connecting way
	 * + = connecting way, intersection
	 * 1 = 
	 * 2 = 
	 * 3 = mål för fiender
	 * 
	 * Nodes;
	 * n = ner
	 * u = upp
	 * v = vänster
	 * h = höger
	 * 
	 * N = start ner
	 * U = start upp
	 * V = start vänster
	 * H = start höger
	 * 
	 */
	List<Point> startPoints = new LinkedList<Point>();
	public Map<Point, List<Point>> startPointsAndPaths;
	
	int MAP_HEIGHT = 8;
	int MAP_WIDTH = 13;
	/**** A sample map ... *****************************************/
	static String map1 =
				 "00h-----n0000\n" + 
				 "00-00000-0000\n" + 
				 "H-u00000h--n0\n" + 
				 "00000000000-0\n" + 
				 "3-v00000n--v0\n" + 
				 "00-00000-0000\n" + 
				 "00u-----v0000\n" +
				 "0000000000000\n"; 

	static char[][] map; // char[y][x] atm just static so we can test
	/**** Ctor *****************************************************/
	public Map_Path(String s) {
		map = toMapArray(s);
		startPointsAndPaths = findPaths(startPoints);
	}
	/**** Ctor methods *********************************************/
	// fill map array with characters, also filter out start points
	private char[][] toMapArray(String s) {
		char[][] m = new char[MAP_HEIGHT][MAP_WIDTH];
		String[] rows = map1.split("\n");
		for (int y = 0; y < rows.length; y++) {
			for (int x = 0; x < rows[y].length(); x++) {
				char c = rows[y].charAt(x);
				if (isStartPoint(c)) 
					startPoints.add(new Point(x, y));
				m[y][x] = rows[y].charAt(x);
			}
		}
		return m;
	}

	// returns a map of <StartPoint, StartPoints path>
	private Map<Point, List<Point>>  findPaths(List<Point> startPoints) {
		Map<Point, List<Point>> pl = new HashMap<Point, List<Point>>();
		for (Point s: startPoints) {
			pl.put(s, findPath(s));
		}
		return pl;
	}
	/**** Helper methods *******************************************/
	private LinkedList<Point> findPath(Point start) { 
		LinkedList<Point> path = new LinkedList<Point>();
		path.add(start);
		int x = start.x, y = start.y;
		Character c = map[y][x];
		while (c != '3'){ // haxx, 3 = goal
			path.addAll(subPath(new Point(x, y)));
			x = path.getLast().x; 
			y = path.getLast().y;
			c = map[y][x];
		}
		return path;
	}
	
	// TODO make this less complex.. works though
	// return a subpath, excluding p but including the next p that could be sent into this function again
	private List<Point> subPath(Point p) {
		List<Point> sp = new LinkedList<Point>();
		int x = p.x, y = p.y;
		Character c = map[y][x];
		
		if (yMods.containsKey(c)) { // check if we should be going up or down
			int d = yMods.get(c); 
			y = y + d;
			c = map[y][x];
			sp.add(new Point(x, y));
			while (isConnectionPoint(c)) {
				y = y + d;
				sp.add(new Point(x, y));
				c = map[y][x];
			}
		} else if (xMods.containsKey(c)) { // check if going left or right
			int d = xMods.get(c);
			x = x + d;
			c = map[y][x];
			sp.add(new Point(x, y));
			while (isConnectionPoint(c)) {
				x = x + d;
				sp.add(new Point(x, y));
				c = map[y][x];
			}
		}
		for (Point pt: sp) 
			System.out.println(pt.x + ", " + pt.y);
		return sp;
	}
	private boolean isStartPoint(Character c) {
		for (Character c1: wayNodes) {
			Character c2 = Character.toUpperCase(c1);
			if (c2.equals(c))
				return true;
		}
		return false;
	}
	// check if the character is of type connection
	private boolean isConnectionPoint(Character c) {
		for (Character cc: connections) {
			if (cc.equals(c))
				return true;
		}
		return false;
	}
	public static void main(String[] args){
		new Map_Path(map1);
		for (int y = 0; y< 8; y++) {
			for (int x = 0; x < 13; x++) {
				char c = map[y][x];
				System.out.print(c);
			}
			System.out.print("\n");
		}
		System.out.println(map[2][0]);
	}
}
